package com.zmn.oms.common.utils;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.zmn.oms.common.constant.CodeEnum;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * 常量枚举序列化器和反序列化器
 *
 * @author hankangshuai
 * @since 2019-10-30
 */
public class CodeEnumSerializerAndDeserializer implements ObjectDeserializer, ObjectSerializer {
    @Override
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
        final JSONLexer lexer = parser.lexer;
        final int token = lexer.token();
        //noinspection unchecked
        Class<CodeEnum> cls = (Class<CodeEnum>) type;
        if (CodeEnum.class.isAssignableFrom(cls)) {
            CodeEnum[] enumConstants = cls.getEnumConstants();
            int value;
            if (token == JSONToken.LITERAL_INT) {
                value = lexer.intValue();
            } else {
                value = Integer.parseInt(lexer.stringVal());
            }
            for (CodeEnum enumConstant : enumConstants) {
                if (enumConstant.getCode() == value) {
                    //noinspection unchecked
                    return (T) enumConstant;
                }
            }
        }
        return null;
    }

    @Override
    public int getFastMatchToken() {
        return JSONToken.LITERAL_INT;
    }

    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.out;
        if (object instanceof CodeEnum) {
            CodeEnum codeEnum = (CodeEnum) object;
            out.writeInt(codeEnum.getCode());
        } else {
            out.writeEnum((Enum<?>) object);
        }
    }
}
